<template>
  <div class="args">
    <div>
      <router-link to="/">返回首页</router-link>
    </div>
    <div class="info">
      <label class="input-label">
        名称
        <input class="input large" type="text" v-model="name" @change="preview">
      </label>
      <label class="input-label">
        作者
        <input class="input large" type="text" v-model="author" @change="preview">
      </label>
      <label class="input-label">
        版本
        <input class="input large" type="text" v-model="version" @change="preview">
      </label>
      <label class="input-label">
        难度
        <input class="input large" type="number" v-model="difficulty" @change="preview">
      </label>
      <label class="input-label">
        <textarea class="introduction" placeholder="说明" type="text" v-model="introduction"></textarea>
      </label>
    </div>
    <div class="scene">
      <label class="input-label">
        场景尺寸
        <input class="input" type="number" v-model="scene.size" :max="60" :min="1" @change="preview">
      </label>
      <label class="input-label">
        食物数量
        <input class="input" type="number" v-model="scene.maxFoodCount" :max="600 / scene.size ** 2 / 5" :min="1"
               @change="preview">
      </label>
      <label class="input-label">
        背景颜色
        <input class="input" type="color" v-model="scene.backgroundColor" @change="preview">
      </label>
      <label class="input-label">
        蛇头颜色
        <input class="input" type="color" v-model="scene.snakeHeadColor" @change="preview">
      </label>
      <label class="input-label">
        蛇身颜色
        <input class="input" type="color" v-model="scene.snakeBodyColor" @change="preview">
      </label>
      <label class="input-label">
        墙体颜色
        <input class="input" type="color" v-model="scene.wallColor" @change="preview">
      </label>
      <label class="input-lab60el">
        食物颜色
        <input class="input" type="color" v-model="scene.foodColor" @change="preview">
      </label>
      <label class="input-label">
        地刺颜色
        <input class="input" type="color" v-model="scene.trapColor" @change="preview">
      </label>
      <label class="input-label">
        传送门颜色
        <input class="input" type="color" v-model="scene.gateColor" @change="preview">
      </label>
    </div>
    <div class="snake">
      <label class="input-label">
        初始速度
        <input class="input" type="number" v-model="snake.speed" :max="15" :min="1" @change="preview">
      </label>
      <label class="input-label">
        蛇头位置
        <input class="input" type="number" v-model="snake.x" :max="scene.size" :min="0" @change="preview">
        <input class="input" type="number" v-model="snake.y" :max="scene.size" :min="0" @change="preview">
      </label>
      <label class="input-label">
        初始蛇长
        <input class="input" type="number" v-model="snake.length" :max="10" :min="1" @change="preview">
      </label>
      <label class="input-label">
        运动方向
        <select v-model="snake.direction" @change="preview">
          <option :value="Direction.Up">上</option>
          <option :value="Direction.Down">下</option>
          <option :value="Direction.Left">左</option>
          <option :value="Direction.Right">右</option>
        </select>
      </label>
    </div>
    <div class="objects">
      <label>
        <button class="btn" @click="addWall">添加墙体</button>
        <input class="input" type="number" v-model="input.wall.x">
        <input class="input" type="number" v-model="input.wall.y">
      </label>
      <label>
        <button class="btn" @click="addGate">添加传送门</button>
        <input class="input" type="number" v-model="input.gate.x">
        <input class="input" type="number" v-model="input.gate.y">
        <input class="input" type="number" v-model="input.gate.x2">
        <input class="input" type="number" v-model="input.gate.y2">
        <select v-model="input.gate.direction">
          <option :value="Direction.Up">上</option>
          <option :value="Direction.Down">下</option>
          <option :value="Direction.Left">左</option>
          <option :value="Direction.Right">右</option>
        </select>
      </label>
      <label>
        <button class="btn" @click="addTrap">添加地刺</button>
        <input class="input" type="number" v-model="input.trap.x">
        <input class="input" type="number" v-model="input.trap.y">
      </label>
    </div>
    <div class="args">
      <div>坐标: {{ point }}</div>
    </div>
    <div class="draw-option">
      <div>
        物件
      </div>
      <div>
        <!--        <label>-->
        <!--          <input type="radio" name="object" value="gate" v-model="objectType">-->
        <!--          传送门-->
        <!--        </label>-->
        <label>
          <input type="radio" name="object" value="walls" v-model="objectType">
          墙体
        </label>
        <label>
          <input type="radio" name="object" value="traps" v-model="objectType">
          地刺
        </label>
        <label>
          <input type="radio" name="object" value="snake" v-model="objectType">
          蛇头
        </label>
      </div>
      <div>
        绘制
      </div>
      <div>
        <label>
          <input :disabled="objectType === 'snake'" type="radio" name="draw-method" value="point-draw"
                 v-model="drawType">
          单点绘制
        </label>
        <label>
          <input :disabled="objectType === 'snake'" type="radio" name="draw-method" value="horizontal-draw"
                 v-model="drawType">
          横向绘制直线
        </label>
        <label>
          <input :disabled="objectType === 'snake'" type="radio" name="draw-method" value="vertical-draw"
                 v-model="drawType">
          纵向绘制直线
        </label>
        <label>
          <input :disabled="objectType === 'snake'" type="radio" name="draw-method" value="rect-draw"
                 v-model="drawType">
          绘制矩形框
        </label>
        <label>
          <input :disabled="objectType === 'snake'" type="radio" name="draw-method" value="fill-rect-draw"
                 v-model="drawType">
          填充矩形
        </label>
        <div class="draw-introduction">
          {{
            {
              'point-draw': '请点击网格绘制物件',
              'horizontal-draw': '请点击一个网格作为起始点，再点击另外一个网格，其横坐标将作为横线终止点',
              'vertical-draw': '请点击一个网格作为起始点，再点击另外一个网格，其横坐标将作为横线终止点',
              'rect-draw': '请点击一个网格作为起始点，再点击另外一个网格作为终止点，将以此为基准绘制矩形框',
              'fill-rect-draw': '请点击一个网格作为起始点，再点击另外一个网格作为终止点，将以此为基准填充矩形',
            }[drawType]
          }}
        </div>
      </div>
    </div>
    <div class="canvas base">
      <canvas ref="preview" :width="600" :height="600" @click="clickCanvas" @mousemove="hoverCanvas"></canvas>
    </div>
    <div class="option base">
      <button class="btn large" @click="preview">预览</button>
      <button class="btn large" @click="clear">清除</button>
      <button class="btn large" @click="clearTraps">清除地刺</button>
      <button class="btn large" @click="clearGates">清除传送门</button>
      <button class="btn large" @click="clearWalls">清除墙体</button>
      <button class="btn large" @click="generate">生成关卡</button>
      <button class="btn large" @click="undo">撤销</button>
      <button class="btn large" @click="redo">重做</button>
      <button class="btn large" @click="upload">上传谱面</button>
    </div>
    <div class="text base">
      {{ json }}
    </div>
  </div>
</template>

<script>
import View from '@/scripts/view'
import Snake from '@/scripts/snake'
import { Direction } from '@/scripts/enum'
import { get, post, put } from '@/scripts/http'

const config = {
  name: '',
  version: '1.0.0',
  author: '-Rain7',
  difficulty: 1,
  introduction: '',
  scene: {
    size: 20,
    backgroundColor: '#000000',
    snakeHeadColor: '#ff0000',
    snakeBodyColor: '#d4d4d4',
    wallColor: '#aa0000',
    foodColor: '#ff0000',
    gateColor: '#00ffff',
    trapColor: '#ffff00',
    maxFoodCount: 5
  },
  snake: {
    x: 10,
    y: 10,
    speed: 7,
    length: 5,
    direction: Direction.Right
  },
  objects: {
    walls: [],
    gates: [],
    traps: []
  }
}

export default {
  name: 'MapEditor',
  data () {
    return {
      ...config,
      input: {
        wall: { x: 0, y: 0 },
        gate: { x: 0, y: 0, x2: 0, y2: 0, direction: Direction.Right },
        trap: { x: 0, y: 0 }
      },
      Direction,
      json: '',
      point: '',
      lastData: [],
      objectType: '',
      drawType: 'point-draw',
      doubleArgFlag: false, //绘制选项标志,
      doubleArgPoint: {}
    }
  },
  async mounted () {
    this.mapId = this.$route.params['mapId']
    if (this.mapId) {
      const map = await get(`/api/maps/${this.mapId}`)
      Object.assign(this, map)
    }
    const canvas = this.$refs['preview']
    const context = canvas.getContext('2d')
    this.view = new View(context, config)
    this.view.init()
    this.view.drawLines()
    this.preview()
    const { name, version, author, scene, snake, objects, introduction, difficulty } = this
    this.json = { name, version, author, scene, snake, objects, introduction, difficulty }
  },
  methods: {
    preview () {
      const { objects: { gates, walls, traps }, snake: { direction, x, y, length }, scene: { size } } = this
      this.view.loadConfig(this.scene)
      this.view.init()
      this.view.drawLines()
      this.view.drawGates(gates)
      this.view.drawWalls(walls)
      this.view.drawTraps(traps)
      this.view.drawSnake(new Snake({ direction, x: +x, y: +y, length, size }))
    },
    addWall () {
      const { x, y } = this.input.wall
      this.objects.walls.push({ x, y })
      this.preview()
    },
    addGate () {
      const gate = this.input.gate
      this.objects.gates.push(gate)
      this.preview()
    },
    addTrap () {
      const { x, y } = this.input.trap
      this.objects.traps.push({ x, y })
      this.preview()
    },
    removeWall () {
      const { x, y } = this.input.wall
      this.objects.walls = this.objects.walls.filter(b => b.x !== x || b.y !== y)
      this.preview()
    },
    removeGate () {
      const { x, y } = this.input.gate
      this.objects.gates = this.objects.gates.filter(b => b.x !== x || b.y !== y)
      this.preview()
    },
    removeTrap () {
      const { x, y } = this.input.trap
      this.objects.traps = this.objects.traps.filter(b => b.x !== x || b.y !== y)
      this.preview()
    },
    clear () {
      this.objects.traps = []
      this.objects.walls = []
      this.objects.gates = []
      this.preview()
    },
    clearTraps () {
      this.objects.traps = []
      this.preview()
    },
    clearWalls () {
      this.objects.walls = []
      this.preview()
    },
    clearGates () {
      this.objects.gates = []
      this.preview()
    },
    undo () {
      alert('暂未实现')
    },
    redo () {
      alert('暂未实现')
    },
    generate () {
      const { name, version, author, scene, snake, objects, introduction, difficulty } = this
      this.json = { name, version, author, scene, snake, objects, introduction, difficulty }
    },
    clickCanvas (e) {
      let { offsetX: x, offsetY: y, shiftKey } = e
      // console.log(e)

      x = Math.floor(x / this.scene.size)
      y = Math.floor(y / this.scene.size)
      this.point = `(${x}, ${y})`

      // {
      //   'point-draw': '请点击网格绘制物件',
      //     'horizontal-draw': '请点击一个网格作为起始点，再点击另外一个网格，其横坐标将作为横线终止点',
      //     'vertical-draw': '请点击一个网格作为起始点，再点击另外一个网格，其横坐标将作为横线终止点',
      //     'rect-draw': '请点击一个网格作为起始点，再点击另外一个网格作为终止点，将以此为基准绘制矩形框',
      //     'fill-rect-draw': '请点击一个网格作为起始点，再点击另外一个网格作为终止点，将以此为基准填充矩形',
      // }
      //

      if (this.objectType === 'snake') {
        Object.assign(this.snake, { x, y })
        this.preview()
        return
      }

      if (this.doubleArgFlag) {
        console.log(this.doubleArgPoint, this.doubleArgFlag, this.drawType)
        this.doubleArgFlag = false
        const { x: a, y: b } = this.doubleArgPoint
        if (this.drawType === 'horizontal-draw') {
          console.log(a, b, x, y)
          for (let i = a; i <= x; i++) {
            this.objects[this.objectType]?.push({ x: i, y })
          }
        } else if (this.drawType === 'vertical-draw') {
          for (let i = b; i <= y; i++) {
            this.objects[this.objectType]?.push({ x, y: i })
          }
        } else if (this.drawType === 'rect-draw') {
          for (let i = a; i <= x; i++) {
            this.objects[this.objectType]?.push({ x: i, y })
            this.objects[this.objectType]?.push({ x: i, y: b })
          }
          for (let i = b + 1; i < y; i++) {
            this.objects[this.objectType]?.push({ x: a, y: i })
            this.objects[this.objectType]?.push({ x, y: i })
          }
        } else if (this.drawType === 'fill-rect-draw') {
          for (let j = b; j <= y; j++) {
            for (let i = a; i <= x; i++) {
              this.objects[this.objectType]?.push({ x: i, y: j })
            }
          }
        }

        this.doubleArgPoint = {}
        this.preview()
        return
      }

      /*
        单点绘制
       */
      if (this.drawType === 'point-draw') {
        this.doubleArgFlag = false
        this.doubleArgPoint = {}
        if (shiftKey) {
          this.objects[this.objectType] = this.objects[this.objectType].filter(b => b.x !== x || b.y !== y)
        } else {
          if (!this.objects[this.objectType]?.find(b => b.x === x && b.y === y))
            this.objects[this.objectType]?.push({ x, y })
        }
      } else {
        this.doubleArgFlag = true
        this.doubleArgPoint = { x, y }
        console.log('开始绘制')
      }
      this.preview()
    },
    hoverCanvas (e) {
      let { offsetX: x, offsetY: y } = e
      x = Math.floor(x / this.scene.size)
      y = Math.floor(y / this.scene.size)
      this.point = `(${x}, ${y})`
    },
    async upload () {
      const { name, version, author, scene, snake, objects, introduction, difficulty } = this
      this.json = { name, version, author, scene, snake, objects, introduction, difficulty }
      if (this.mapId) {
        await put(`/api/maps/${this.mapId}`, this.json)
      } else await post('/api/maps', this.json)
      alert('上传成功')
    }
  }
}
</script>

<style scoped>
.args {
  display: flex;
  justify-content: flex-start;
  align-items: stretch;
  flex-direction: column;
  margin-bottom: 20px;
}

.input {
  width: 50px;
  border: 1px solid #000;
  outline: none;
  -webkit-border-radius: 0;
  -moz-border-radius: 0;
  border-radius: 0;
  margin: 10px 5px;
  text-align: center;
}

[type=color].input {
  padding: 0;
  border: none;
  background-color: transparent;
}

.btn {
  -webkit-border-radius: 0;
  -moz-border-radius: 0;
  border-radius: 0;
  border: 1px solid #000;
  background-color: #e9e9e9;
  outline: none;
}

.btn:hover {
  background-color: #fff;
  cursor: pointer;
}

.canvas {
  padding: 10px;
  border: 1px solid #000;
}

.objects {
  display: flex;
  justify-content: flex-start;
  align-items: flex-start;
  flex-direction: column;
}

.btn:active {
  background-color: #a0a0a0;
}

.btn.large {
  min-width: 50px;
  margin-right: 10px;
}

.option {
  margin-top: 20px;
}

.text {
  border: 1px solid #000;
  padding: 10px;
  margin-top: 20px;
  min-height: 40px;
}

.info {
  display: flex;
  justify-content: flex-start;
  align-items: flex-start;
  flex-direction: column;
}

.input.large {
  width: 400px;
}

.base {
  width: 600px;
}

.draw-option {
  margin-bottom: 20px;
}

textarea.introduction {
  width: 450px;
  border: 1px solid #000;
  -webkit-border-radius: 0;
  -moz-border-radius: 0;
  border-radius: 0;
  height: 80px;
  resize: vertical;
  outline: none;
  padding: 5px;
  box-sizing: border-box;
}

.draw-introduction {
  margin-top: 10px;
  color: red;
  font-size: 14px;
}
</style>